﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;

namespace KT
{
    public partial class Form1 : Form
    {
        Bitmap _tmpB;
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //设置文件的类型

            openFileDialog1.Filter = "*.jpg,*.jpeg,*.bmp,*.gif,*.ico,*.png,*.tif,*.wmf|*.jpg;*.jpeg;*.bmp;*.gif;*.ico;*.png;*.tif;*.wmf";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)                            //打开文件对话框
            {
                //根据文件的路径创建Image对象

                Image myImage = System.Drawing.Image.FromFile(openFileDialog1.FileName);

                SrcImage.Image = myImage;                                          //显示打开的图片
                this.button2.Enabled = true;
            }
        }
       
        /// <summary>
        /// 提取特征点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            Image myImage = System.Drawing.Image.FromFile(openFileDialog1.FileName);
            SrcImage.Image = myImage;
            PicCut(openFileDialog1.FileName);
        }

        public  bool zft(Bitmap b, out double[,] huiduzhi)
        {
            int[] gray = new int[256];
            int[] rr = new int[256];
            int[] gg = new int[256];
            int[] bb = new int[256];
            int tt = 0;
            foreach (int i in gray)
            {
                gray[i] = 0;
            }
            foreach (int i in rr)
            {
                rr[i] = 0;
            }
            foreach (int i in gg)
            {
                gg[i] = 0;
            }
            foreach (int i in bb)
            {
                bb[i] = 0;
            }

            // GDI+ still lies to us - the return format is BGR, NOT RGB.
            BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = bmData.Stride;
            System.IntPtr Scan0 = bmData.Scan0;
            int nWidth = b.Width;
            int nHeight = b.Height;
            double[,] hdz = new double[nWidth, nHeight];

            unsafe
            {
                byte* p = (byte*)(void*)Scan0;

                int nOffset = stride - b.Width * 3;

                byte red, green, blue;
                for (int y = 0; y < nHeight; ++y)
                {
                    for (int x = 0; x < nWidth; ++x)
                    {
                        blue = p[0];
                        green = p[1];
                        red = p[2];

                        tt = p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
                        hdz[x, y] = tt;
                        rr[red]++;
                        gg[green]++;
                        bb[blue]++;
                        gray[tt]++;   //统计灰度值为tt的象素点数目  
                        p += 3;
                    }
                    p += nOffset;
                }
            }
            b.UnlockBits(bmData);
            huiduzhi = hdz;
            return true;
        }

        //截取图片  主要操作区域
        private  void cutImage(Image SrcImage, Point pos, int cutWidth, int cutHeight, out Image toImage)
        {

            //先初始化一个位图对象，来存储截取后的图像
            Bitmap bmpDest = new Bitmap(cutWidth, cutHeight, PixelFormat.Format32bppRgb);
            Graphics g = Graphics.FromImage(bmpDest);



            //这个矩形定义了，你将要在被截取的图像上要截取的图像区域的左顶点位置和截取的大小
            Rectangle rectSource = new Rectangle(pos.X, pos.Y, cutWidth, cutHeight);

            //这个矩形定义了，你将要把 截取的图像区域 绘制到初始化的位图的位置和大小
            //我的定义，说明，我将把截取的区域，从位图左顶点开始绘制，绘制截取的区域原来大小
            Rectangle rectDest = new Rectangle(0, 0, cutWidth, cutHeight);

            //第一个参数就是加载你要截取的图像对象，第二个和第三个参数及如上所说定义截取和绘制图像过程中的相关属性，第四个属性定义了属性值所使用的度量单位
            g.DrawImage(SrcImage, rectDest, rectSource, GraphicsUnit.Pixel);

            //这是在GUI上显示被截取的图像
            toImage = (Image)bmpDest;

            g.Dispose();
            SrcImage.Dispose();
        }
        /// <summary>
        /// 提取特征点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private  void PicCut(string objfileFull)
        {
            DateTime d1 = DateTime.Now;
            Image SrcImage = System.Drawing.Image.FromFile(objfileFull);

            Log.Info("info", "取得原图片转化为IMAGE:");

            int Var_H = SrcImage.Height;                          //获取图象的高度

            int Var_W = SrcImage.Width;                           //获取图象的宽度

            Bitmap Var_bmp = (Bitmap)SrcImage;                    //根据图象的大小创建Bitmap对象
            Log.Info("info", "转化为BITMAP:");

            double[,] huiduzhi = new double[Var_W, Var_H];                       //用于存储各点灰度值

            zft(Var_bmp, out huiduzhi);
            Log.Info("info", "灰度结束:");

            //每100个像素判断灰度值比列
            int i = 0;
            int par = 0;
            int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
            int jy = 0;
            //判断左上角坐标
            for (int x = 0; x < Var_W - 2; x = x + 10)
            {
                i = 0;
                for (int y = 0; y < Var_H - 2; y=y+5)
                {
                    if (huiduzhi[x, y] > 60)
                        par++;
                    if (i>0 && i % 100 == 0)
                    {
                        if (par > 60)
                        {
                            if (jy == 0)
                            {
                                y1 = y;
                                x1 = x;
                                jy++;
                            }
                            else
                            {
                                if (y < y1)
                                    y1 = y;
                            }
                        }
                        par = 0;
                    }
                    i++;
                }
            }

            Log.Info("info", "判断左上角坐标:" + x1 + " " + y1);
            jy = 0;
            //判断右下角坐标
            for (int x = Var_W - 2; x > 0; x = x - 10)
            {
                i = 0;
                for (int y = Var_H - 2; y > 0; y=y-5)
                {
                    if (huiduzhi[x, y] > 60)
                        par++;
                    if (i > 0 && i % 100 == 0)
                    {
                        if (par > 60)
                        {
                            if (jy == 0)
                            {
                                y2 = y;
                                x2 = x;
                                jy++;
                            }
                            else
                            {
                                if (y > y2)
                                    y2 = y;
                            }
                        }
                        par = 0;
                    }
                    i++;
                }
            }
            Log.Info("info", "判断右下角坐标:" + x2 + " " + y2);
            //补偿
            x1 = x1 < 10 ? x1 : x1 - 5;
            x2 = x2 + 10 > Var_W ? Var_W : x2 + 10;
            y1 = y1 < 451 ? y1 : y1 - 450;
            y2 = y2 + 451 > Var_H ? Var_W : y2 + 450;
            int cutW = x2 - x1;
            int cutH = y2 - y1;
            Log.Info("info", "补偿结束");


            //调正
            jy = 0;
            //判断左下角坐标
            int x3 = -1, y3 = -1;
            //三角函数,已知两边求角度
            double a = 0, b = 0, c = 0,A = 0;
            for (int x = 0; x < Var_W - 2; x = x + 10)
            {
                i = 0;
                for (int y = Var_H - 2; y > 0; y = y - 5)
                {
                    if (huiduzhi[x, y] > 60)
                        par++;
                    if (i > 0 && i % 100 == 0)
                    {
                        if (par > 60)
                        {
                            if (jy == 0)
                            {
                                y3 = y;
                                x3 = x;
                                jy++;
                                break;
                            }
                        }
                        par = 0;
                    }
                    i++;
                }
                if (x3 >= 0)
                    break;
            }
            a = Math.Abs( x3 - x1);
            b = Math.Abs(y3 - y1);
            c = Math.Sqrt( a * a + b * b);
            A = Math.Asin(a / c) / Math.PI * 180;
            textBox1.Text = A.ToString();

            //切图
            Point p = new Point(x1, y1);
            Image toImage;
            SrcImage.Dispose();
            Image SrcImage2 = System.Drawing.Image.FromFile(objfileFull);
            cutImage(SrcImage2, p, cutW, cutH, out toImage);
            this.toImage.Image = toImage;
            Log.Info("info", "切图结束");
            //再次保存
            //toImage.Save(objfileFull, ImageFormat.Jpeg);
            //Log.Info("info", "切图保存结束");

            Image SrcImage3 = System.Drawing.Image.FromFile(objfileFull);
            pic_tz.Image = KiRotate((Bitmap)SrcImage3, float.Parse( A.ToString()), Color.Transparent);
            string id = Guid.NewGuid().ToString();
            this.pic_tz.Image.Save(@"d:/pic/" + id + ".jpg", ImageFormat.Jpeg);


            id = Guid.NewGuid().ToString();
            this.toImage.Image.Save(@"d:/pic/" + id + ".jpg", ImageFormat.Jpeg);

            DateTime d2 = DateTime.Now;
            double ss = d2.Subtract(d1).TotalSeconds;
            Log.Info("info", "用时" + ss + "s");
        }

        #region GetPicThumbnail
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="sFile">原图片</param>
        /// <param name="dFile">压缩后保存位置</param>
        /// <param name="dHeight">高度</param>
        /// <param name="dWidth"></param>
        /// <param name="flag">压缩质量 1-100</param>
        /// <returns></returns>

        public bool GetPicThumbnail(Image sFile, string dFile, int dHeight, int dWidth, int flag)
        {
            System.Drawing.Image iSource = sFile;

            ImageFormat tFormat = iSource.RawFormat;

            int sW = 0, sH = 0;

            //按比例缩放

            Size tem_size = new Size(iSource.Width, iSource.Height);



            if (tem_size.Width > dHeight || tem_size.Width > dWidth) //将**改成c#中的或者操作符号
            {

                if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
                {

                    sW = dWidth;

                    sH = (dWidth * tem_size.Height) / tem_size.Width;

                }

                else
                {

                    sH = dHeight;

                    sW = (tem_size.Width * dHeight) / tem_size.Height;

                }

            }

            else
            {

                sW = tem_size.Width;

                sH = tem_size.Height;

            }

            Bitmap ob = new Bitmap(dWidth, dHeight);

            Graphics g = Graphics.FromImage(ob);

            g.Clear(Color.WhiteSmoke);

            g.CompositingQuality = CompositingQuality.HighQuality;

            g.SmoothingMode = SmoothingMode.HighQuality;

            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);

            g.Dispose();

            //以下代码为保存图片时，设置压缩质量

            EncoderParameters ep = new EncoderParameters();

            long[] qy = new long[1];

            qy[0] = flag;//设置压缩的比例1-100

            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);

            ep.Param[0] = eParam;

            try
            {

                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();

                ImageCodecInfo jpegICIinfo = null;

                for (int x = 0; x < arrayICI.Length; x++)
                {

                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {

                        jpegICIinfo = arrayICI[x];

                        break;

                    }

                }

                if (jpegICIinfo != null)
                {

                    ysimage.Image = ob;
                    ysimage.Image.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径

                }

                else
                {

                    ob.Save(dFile, tFormat);

                }

                return true;

            }

            catch
            {

                return false;

            }

            finally
            {

                //iSource.Dispose();

                //ob.Dispose();

            }



        }
        #endregion

        /// <summary>
        /// 任意角度旋转
        /// </summary>
        /// <param name="bmp">原始图Bitmap</param>
        /// <param name="angle">旋转角度</param>
        /// <param name="bkColor">背景色</param>
        /// <returns>输出Bitmap</returns>
        public static Bitmap KiRotate(Bitmap bmp, float angle, Color bkColor)
        {
            int w = bmp.Width + 2;
            int h = bmp.Height + 2;

            PixelFormat pf;

            if (bkColor == Color.Transparent)
            {
                pf = PixelFormat.Format32bppArgb;
            }
            else
            {
                pf = bmp.PixelFormat;
            }

            Bitmap tmp = new Bitmap(w, h, pf);
            Graphics g = Graphics.FromImage(tmp);
            g.Clear(bkColor);
            g.DrawImageUnscaled(bmp, 1, 1);
            g.Dispose();

            GraphicsPath path = new GraphicsPath();
            path.AddRectangle(new RectangleF(0f, 0f, w, h));
            Matrix mtrx = new Matrix();
            mtrx.Rotate(angle);
            RectangleF rct = path.GetBounds(mtrx);

            Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
            g = Graphics.FromImage(dst);
            g.Clear(bkColor);
            g.TranslateTransform(-rct.X, -rct.Y);
            g.RotateTransform(angle);
            g.InterpolationMode = InterpolationMode.HighQualityBilinear;
            g.DrawImageUnscaled(tmp, 0, 0);
            g.Dispose();

            tmp.Dispose();

            return dst;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            string id = Guid.NewGuid().ToString();
            ysimage.Image.Save(@"d:/pic/" + id + ".jpg",ImageFormat.Jpeg);
        }

        [DllImport(@"E:\ C ++\timetest\debug\MyDll.dll", CharSet = CharSet.Ansi, EntryPoint = "MyCDll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int MyCDll(int a, int b);

        private void ysbutton_Click(object sender, EventArgs e)
        {
            string id = Guid.NewGuid().ToString();
            GetPicThumbnail(toImage.Image, @"d:/pic/" + id + ".jpg", toImage.Image.Height * 60 / 100, toImage.Image.Height * 60 / 100, 80);
        }

        private void btn_tz_Click(object sender, EventArgs e)
        {

        }
    }
}
